package user

import (
	"crypto/md5"
	"errors"
	"fmt"
	"go-ddd-ecommerce/internal/domain/events"
	"unicode/utf8"

	"github.com/google/uuid"
)

// User 用户实体 - 充血模型
type User struct {
	ID       uuid.UUID // 使用UUID更符合DDD设计
	Username string
	Password string
	Balance  float64
	events   []events.DomainEvent // 记录领域事件,临时存储待发布的事件
}

// NewUser 创建用户-工厂方法
func NewUser(username, password string) (*User, error) {
	if err := validateUsername(username); err != nil {
		return nil, err
	}
	if err := validatePassword(password); err != nil {
		return nil, err
	}
	user := &User{
		ID:       uuid.New(),
		Username: username,
		Password: hashPaassword(password),
		Balance:  0.0,
		events:   make([]events.DomainEvent, 0),
	}
	// 发布新增用户事件
	user.events = append(user.events, events.NewUserCreatedEvent(user.ID, username, user.Balance))
	return user, nil
}

// UpdatePassword 更新密码
func (u *User) UpdatePassword(newPassword string) error {
	if err := validatePassword(newPassword); err != nil {
		return err
	}
	u.Password = hashPaassword(newPassword)
	// 发布修改密码事件
	u.events = append(u.events, events.NewUserPasswordUpdateEvent(u.ID))
	return nil
}

// 添加余额
func (u *User) AddBalance(amount float64) error {
	if amount < 0 {
		return errors.New("金额不能小于0")
	}
	u.Balance += amount

	// 发布余额增加事件
	u.events = append(u.events, events.NewUserBalanceUpdateEvent(u.ID, amount, u.Balance))
	return nil
}

// 扣除余额
func (u *User) SubBalance(amount float64) error {
	if amount < 0 {
		return errors.New("金额不能小于0")
	}
	if u.Balance < amount {
		return errors.New("余额不足")
	}
	u.Balance -= amount

	// 发布余额扣减事件
	u.events = append(u.events, events.NewUserBalanceUpdateEvent(u.ID, -amount, u.Balance))
	return nil
}

// GetDomainEvents 获取待发布的事件
// 实现事件生产器的接口
func (u *User) GetDomainEvents() []events.DomainEvent {
	return u.events
}

// ClearDomainEvents 清空已发布的事件
// 实现事件生产器的接口
func (u *User) ClearDomainEvents() {
	u.events = make([]events.DomainEvent, 0)
}

// 私有方法 - 验证规则
func validateUsername(username string) error {
	if utf8.RuneCountInString(username) < 3 || utf8.RuneCountInString(username) > 20 {
		return errors.New("用户名长度必须在3-20个字符之间")
	}
	return nil
}

func validatePassword(password string) error {
	if utf8.RuneCountInString(password) < 6 || utf8.RuneCountInString(password) > 20 {
		return errors.New("密码长度必须在6-20个字符之间")
	}
	return nil
}

func hashPaassword(password string) string {
	// 使用简单的加密算法
	return fmt.Sprintf("%x", md5.Sum([]byte(password)))
}
